#ifndef QP_QEQUEUE_HPP
#define QP_QEQUEUE_HPP
#include <memory>

#include "QEvt.hpp"

namespace QP {

using QEQueueCtr = unsigned int;

class QEvt;

class QEQueue {
 public:
  QEQueue() noexcept;

  void init(std::shared_ptr<const QEvt> qSto[], QEQueueCtr qLen) noexcept;
  void postFIFO(const std::shared_ptr<const QEvt> &e) noexcept;
  void postLIFO(const std::shared_ptr<const QEvt> &e) noexcept;

  std::shared_ptr<const QEvt> get(void);

  QEQueueCtr getNFree(void) const noexcept { return m_nFree; }
  QEQueueCtr getNMin(void) const noexcept { return m_nMin; }
  bool isEmpty(void) const noexcept { return m_frontEvt == nullptr; }

 private:
  //! disallow copying of QEQueue
  QEQueue(QEQueue const &) = delete;
  //! disallow assignment of QEQueue
  QEQueue &operator=(QEQueue const &) = delete;

 private:
  std::shared_ptr<const QEvt> m_frontEvt;
  std::shared_ptr<const QEvt> *m_ring;
  //! offset of the end of the ring buffer from the start of the buffer
  QEQueueCtr m_end;
  //! offset to where next event will be inserted into the buffer
  QEQueueCtr volatile m_head;
  //! offset of where next event will be extracted from the buffer
  QEQueueCtr volatile m_tail;
  //! number of free events in the ring buffer
  QEQueueCtr volatile m_nFree;
  //! minimum number of free events ever in the ring buffer.
  /// @note this attribute remembers the low-watermark of the ring buffer,
  /// which provides a valuable information for sizing event queues.
  /// @sa QP::QF::getQueueMin().
  QEQueueCtr m_nMin;

 private:
  friend class QF;
  friend class QActive;
};
}

#endif  // QP_QEQUEUE_HPP
